package com.chenfan.finance.utils;

import com.chenfan.finance.commons.UserVO;
import com.chenfan.finance.enums.OperateLockEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;

import javax.validation.ValidationException;
import java.lang.reflect.Field;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author liran
 */
@Slf4j
public class OperateUtil {

    public static Object setValueByPropName(Object origin, String propName, Object value) {
        try {
            Field field = origin.getClass().getDeclaredField(propName);
            field.setAccessible(true);
            if (field.getType().isInstance(LocalDateTime.now()) && value.getClass().isInstance(new Date())) {
                value = dateToLocalDateTime((Date) value);
            }
            field.set(origin, value);
        } catch (Exception e) {
            log.error("反射赋值对象属性异常", e);
            return null;
        }
        return value;
    }

    /**
     * @param origin
     * @param userVO
     */

    public static void onSave(Object origin, UserVO userVO) {
        if (userVO == null) {
            throw new ValidationException("无法获取到登录用户");
        }
        setValueByPropName(origin, "createBy", userVO.getUserId());
        setValueByPropName(origin, "updateBy", userVO.getUserId());
        Date now = new Date();
        setValueByPropName(origin, "createDate", now);
        setValueByPropName(origin, "updateDate", now);
        setValueByPropName(origin, "createName", userVO.getRealName());
        setValueByPropName(origin, "updateName", userVO.getRealName());

        setValueByPropName(origin, "companyId", userVO.getCompanyId());

    }

    /**
     * @param origin
     * @param userVO
     */

    public static void onUpdate(Object origin, UserVO userVO) {
        if (userVO == null) {
            throw new ValidationException("无法获取到登录用户");
        }
        setValueByPropName(origin, "updateBy", userVO.getUserId().longValue());
        Date now = new Date();
        setValueByPropName(origin, "updateDate", now);
        setValueByPropName(origin, "updateName", userVO.getRealName());
    }

    /**
     * Date -> LocalDateTime
     *
     * @param date
     * @return
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        return LocalDateTime.ofInstant(instant, zone);
    }

    public static Date getEndTime(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTime();
    }

    static ConcurrentHashMap<String, ReentrantLock> lockMap = new ConcurrentHashMap<>();

    public static ReentrantLock getLock(String key, OperateLockEnum type) {
        key = type.getKey() + key;
        Assert.isTrue(lockMap.get(key) == null, type.getErrMsg() + "，中...，请稍后再试");
        lockMap.putIfAbsent(key, new ReentrantLock());
        return lockMap.get(key);
    }

    public static void removeLock(String key, OperateLockEnum type, ReentrantLock lock) {
        key = type.getKey() + key;
        if (lockMap.get(key).equals(lock)) {
            lockMap.remove(key);
        }
    }

}
